using System;
using System.Collections;

namespace Meta
{
	/// <summary>
	/// Collection class with weak pointers.
	/// </summary>
	public class WeakList : IList
	{
		ArrayList elements = new ArrayList();
		public WeakList()
		{
		}

		IEnumerator IEnumerable.GetEnumerator() {
			return new Enumerator(this);
		}

		class Enumerator : System.Collections.IEnumerator {
			WeakList list;
			int position=-1;

			public Enumerator(WeakList list) {
				this.list = list;
			}

			void IEnumerator.Reset() {
				position = -1;
			}

			object IEnumerator.Current {
				get {
					return ((WeakReference)list.elements[position]).Target;
				}
			}

			bool IEnumerator.MoveNext() {
				position++;
				while (position<list.elements.Count) {
					WeakReference e = (WeakReference)list.elements[position];
					if (e.IsAlive)
						return true;
					else
						list.elements.RemoveAt(position);
				}
				return false;
			}
		}

		void Clean() {
			// Clear out elements that have been GC'ed
			for (int i=elements.Count-1; i>=0; i--) {
				if (!((WeakReference)elements[i]).IsAlive)
					elements.RemoveAt(i);
			}
		}

		bool IList.IsFixedSize {
			get {
				return false;
			}
		}

		bool IList.IsReadOnly {
			get {
				return false;
			}
		}

		void IList.Clear() {
			elements.Clear();
		}

		bool IList.Contains(object x) {
			for (int i=elements.Count-1; i>=0; i--) {
				WeakReference e = (WeakReference)elements[i];
				if (!e.IsAlive)
					elements.RemoveAt(i);
				else if (e.Target==x)
					return true;
			}
			return false;
		}

		int IList.Add(object value) {
				return elements.Add (new WeakReference(value));
		}

		int ICollection.Count {
			get {
				Clean();
				return elements.Count;
			}
		}

		void IList.Remove(object obj) {
				for (int i=elements.Count-1; i>=0; i--) {
					WeakReference e = (WeakReference)elements[i];
					if (!e.IsAlive || e.Target==obj)
						elements.RemoveAt(i);
				}
		}

		void ICollection.CopyTo(Array a, int index) {
			Clean();
			elements.CopyTo(a, index);
		}

		bool ICollection.IsSynchronized {
			get {
				return false;
			}
		}

		object ICollection.SyncRoot {
			get {
				return this;
			}
		}

		int IList.IndexOf(object x) {
			throw new NotSupportedException();
		}

		object IList.this[int x] {
			get {
				throw new NotSupportedException();
			}
			set {
				throw new NotSupportedException();
			}
		}

		void IList.Insert(int index, object x) {
			throw new NotSupportedException();
		}

		void IList.RemoveAt(int x) {
			throw new NotSupportedException();
		}


	}
}
